package com.lwy.setter.setters;


import com.lwy.setter.BaseNameSetter;
import com.lwy.setter.NameSetterMeta;
import com.lwy.setter.annos.EnumCode;
import com.lwy.setter.enums.CnEnumCache;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.lwy.setter.types.StringOption;


import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <br/>
 *
 * @author bukong
 * @date 2022/7/5
 */
@Component
public class EnumCodeNameSetter extends BaseNameSetter<EnumCode> {

    @Override
    public boolean isFillNameByCode() {
        return true;
    }

    @Override
    protected Class<EnumCode> getAnnotationClz() {
        return EnumCode.class;
    }

    @Override
    public <T> void fillNameByCode(List<T> beans, Class<T> tClass) {
        if (CollectionUtils.isEmpty(beans)) {
            return;
        }
        try {
            // code - name 字段映射
            final Map<Field, Field> fieldMapper = NameSetterMeta.getFieldMapper(tClass, getAnnotationClz());
            Set<Long> ids = new HashSet<>();
            // 解析字典项
            Set<String> enumTypes = new HashSet<>();
            List<String> parentCodes = new ArrayList<>();
            for (Field markedField : fieldMapper.keySet()) {
                final EnumCode annotation = markedField.getAnnotation(getAnnotationClz());
                String typeCode = annotation.typeCode();
                for (T bean : beans) {
                    final Object markedFieldVal = markedField.get(bean);
                    if (markedFieldVal == null) {
                        continue;
                    } else {
                        enumTypes.add(typeCode);
                    }
                }
            }
            // 查询枚举项
            Map<String, String> nameMap = new HashMap<>();
            for (String enumType : enumTypes) {
                Optional.ofNullable(CnEnumCache.getNameOptions(enumType))
                        .ifPresent(enumItems -> nameMap.putAll(enumItems.stream().collect(Collectors.toMap(item -> enumType + "#" + item.getValue(), StringOption::getLabel))));
            }
            // 填充 name
            for (Map.Entry<Field, Field> entry : fieldMapper.entrySet()) {
                final Field markedField = entry.getKey();
                final Field nameField = entry.getValue();
                for (T bean : beans) {
                    final Object markedFieldVal = markedField.get(bean);
                    final EnumCode annotation = markedField.getAnnotation(getAnnotationClz());
                    String parentCode = annotation.typeCode();
                    if (markedFieldVal == null) {
                        continue;
                    } else if (markedFieldVal instanceof CharSequence) {
                        final String fieldNameKey = parentCode + "#" + markedFieldVal;
                        if (nameMap.containsKey(fieldNameKey)) {
                            nameField.set(bean, nameMap.get(fieldNameKey));
                        }
                    } else if (markedFieldVal instanceof Collection) {
                        List<String> markedFieldValues = ((Collection<?>) markedFieldVal).stream().map(Object::toString).collect(Collectors.toList());
                        List<String> nameList = markedFieldValues.stream()
                                .map(val -> parentCode + "#" + val)
                                .map(nameMap::get).collect(Collectors.toList());
                        nameField.set(bean, nameList);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

}
